package net.aiion.weave.impl.bytecode.asm;

import net.aiion.weave.asm.AnnotationVisitor;
import net.aiion.weave.asm.Attribute;
import net.aiion.weave.asm.FieldVisitor;
import net.aiion.weave.asm.Opcodes;
import net.aiion.weave.spi.bytecode.BytecodeEventFactory;

public class BytecodeASMFieldVisitor extends FieldVisitor implements Opcodes
{
    private final BytecodeEventFactory mBytecodeEventFactory;
    private final BytecodeASMAction mBytecodeAction;

    private BytecodeASMAnnotationVisitor annotationVisitor;

    private boolean isCancelled;

    public BytecodeASMFieldVisitor(final BytecodeEventFactory aBytecodeEventFactory,
        final BytecodeASMAction aBytecodeAction)
    {
        super(ASM4);
        mBytecodeEventFactory = aBytecodeEventFactory;
        mBytecodeAction = aBytecodeAction;
    }

    public void cancelVisitation() {
        isCancelled = true;

        if (annotationVisitor != null) {
            annotationVisitor.cancelVisitation();
        }
    }

    /*
     * The methods of this class must be called in the following order: 
     * ( visitAnnotation | visitAttribute )* visitEnd.
     */

    @Override
    public AnnotationVisitor visitAnnotation(final String aDescriptor, final boolean aVisible) {
        if (isCancelled) {
            return null;
        }

        mBytecodeAction.processBytecode(mBytecodeEventFactory.createAnnotationStart(aDescriptor, aVisible));
        annotationVisitor = new BytecodeASMAnnotationVisitor(mBytecodeEventFactory, mBytecodeAction);
        return annotationVisitor;
    }

    @Override
    public void visitAttribute(final Attribute aAttribute) {
        if (isCancelled) {
            return;
        }

        mBytecodeAction.processBytecode(mBytecodeEventFactory.createAttribute(aAttribute));
    }

    @Override
    public void visitEnd() {
        if (isCancelled) {
            return;
        }

        mBytecodeAction.processBytecode(mBytecodeEventFactory.createFieldEnd());
    }
}
